package com.sxsihe.heartmate.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.FloatMath;
import android.view.MotionEvent;
import android.view.View;

import com.sxsihe.heartmate.R;
import com.sxsihe.heartmate.util.SharePreferenceUtil;

import java.util.ArrayList;
import java.util.List;

public class ECGView2 extends View {
    ArrayList<Point> mPoints;
    float startX = 0;
    float offsetX = 0;
    float startY = 0;
    float offsetY = 0;
    double oldDist;
    double scale = 1;
    //相对于屏幕的两指中心
    float fingerCenterX = 0;
    float fingerCenterY = 0;
    float accumulate_scale = 1;
    int mode = 0;
    private Paint paint;
    private Paint mPaint1;
    private Paint mPaint2;
    private Paint mPaint3;
    Bitmap mBufferBitmap;
    Canvas mCanvas;
    SharePreferenceUtil spu;
    private int step = 20;
    private float strokeWidth = 4.0f;

    public ECGView2(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context);
    }

    public ECGView2(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView(context);
    }

    public ECGView2(Context context) {
        super(context);
        initView(context);
    }

    private void initView(Context context) {
        if (spu == null) {
            spu = SharePreferenceUtil.getInstance(context);
        }
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setFilterBitmap(true);
        paint.setColor(Color.BLACK);

        mPaint1 = new Paint();
        mPaint1.setColor(spu.getColor("line_color", getResources().getColor(R.color.ecgview_line_color)));
        mPaint1.setStyle(Paint.Style.FILL);
        mPaint1.setAntiAlias(true);
        mPaint1.setFilterBitmap(true);
        mPaint1.setStrokeWidth(strokeWidth);

        mPaint2 = new Paint();
        mPaint2.setStyle(Paint.Style.FILL);
        mPaint2.setColor(Color.GRAY);
        mPaint2.setAntiAlias(true);
        mPaint2.setFilterBitmap(true);
        mPaint2.setStrokeWidth(10);

        mPaint3 = new Paint();
        mPaint3.setColor(spu.getColor("coordinate_color", getResources().getColor(R.color.ecgview_coordinate_color)));
        mPaint3.setStyle(Paint.Style.FILL);
        mPaint3.setAntiAlias(true);
        mPaint3.setAlpha(50);
        mPaint3.setStrokeWidth((float) 1);

        mCanvas = new Canvas();
    }

    private boolean prepare() {
        if (mPoints == null || mPoints.isEmpty()) {
            return false;
        }
        return true;
    }

    List<Point> points;
    int height;
    int width;
    float end;
    float start;

    /**
     *根据当前偏移量得到当前屏幕显示的point
     * @param offsetX 当前偏移量
     * @return
     */
    private float[] convertToPts(float offsetX) {

        //当像素与坐标为1:1时应该在屏幕绘制的point的长度
        end = (offsetX + width)/accumulate_scale;
        //长度与文件中点数的处理
        if ((offsetX + width)/accumulate_scale > mPoints.size() - 1) {
            end = mPoints.size() - 1;
        } else if (end < 0) {
            end = 0;
        }
        //起始点
        start = offsetX/accumulate_scale;
        //起始点与文件中点数的处理
        if (offsetX <= 0) {
            start = 0;
        } else if (start > mPoints.size() - 1) {
            start = mPoints.size() - 1;
        }
        int size = (int) (((end - start) - 1) * 4);
        if (size < 0) size = 0;
        //从原文件取出的需要绘制点
        points = mPoints.subList((int)start, (int)end+1);
        float[] pts = new float[size];
        for (int i = 0; i < size; i++) {
            int pointIndex = (i + 2) / 4;
            if (i % 2 == 1) {
                pts[i] = accumulate_scale*(points.get(pointIndex).y - offsetY) + height / 2;
            } else {
                pts[i] = accumulate_scale*(points.get(pointIndex).x )- offsetX;
            }
        }
        return pts;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mBufferBitmap = Bitmap.createBitmap(getViewWidth(), getViewHeight(), Bitmap.Config.ARGB_8888);
        mCanvas.setBitmap(mBufferBitmap);
        canvas.drawColor(spu.getColor("bg_color", getResources().getColor(R.color.ecgview_bg_color)));
        width = getViewWidth();
        height = getViewHeight();

        if ((offsetX+width)/accumulate_scale > mPoints.size() ) {
            offsetX = mPoints.size()*accumulate_scale - width;
        }
        if (offsetX < 0) {
            offsetX = 0;
        }
        drawCoords();

        drawLogo();

        drawProgress();

         if (prepare()) {
            float pts[] = convertToPts(offsetX);
            if (pts.length > 0) {
                mCanvas.drawLines(pts, mPaint1);
            }
        }
        canvas.drawBitmap(mBufferBitmap, 0, 0, paint);
    }

    public void drawLogo(){
        Bitmap bmp= BitmapFactory.decodeResource(getResources(), R.drawable.zhc_logo_view);
        mCanvas.drawBitmap(bmp, width - bmp.getWidth() - 30, height - bmp.getHeight() - 30, paint);
    }

    public void drawProgress(){
        float barWidth = width * (width / ((float) mPoints.size() * accumulate_scale));
        float left = offsetX/(mPoints.size()*accumulate_scale)*width;
        Rect r = new Rect((int)(left), height - 10, (int) (left+barWidth), height);
        mCanvas.drawRect(r,mPaint2);
    }

    public void drawCoords() {
        int index = 0;
        for (float i = -offsetX; i < width; i += step*accumulate_scale) {
            if (index % 5 == 0) {
                mPaint3.setStrokeWidth(3);
            }
            mCanvas.drawLine(i, 0, i, height, mPaint3);
            if (index % 5 == 0) {
                mPaint3.setStrokeWidth(1);
            }
            index++;
        }
        index = 0;
        for (float i = height/2; i > 0; i -= step*accumulate_scale) {
            if (index % 5 == 0 && index != 0) {
                mPaint3.setStrokeWidth(3);
            }
            mCanvas.drawLine(0, i, width, i, mPaint3);
            if (index % 5 == 0) {
                mPaint3.setStrokeWidth(1);
            }
            index++;
        }

        index = 0;
        for (float i = height/2; i < height; i += step*accumulate_scale) {
            if (index % 5 == 0 && index != 0) {
                mPaint3.setStrokeWidth(3);
            }
            mCanvas.drawLine(0, i, width, i, mPaint3);
            if (index % 5 == 0) {
                mPaint3.setStrokeWidth(1);
            }
            index++;
        }
    }

    public void addPoint(Point point) {
        if (this.mPoints == null) {
            this.mPoints = new ArrayList<Point>();
        }
        this.mPoints.add(point);
        invalidate();
    }

    private int getViewHeight() {
        return this.getHeight();
    }

    private int getViewWidth() {
        return this.getWidth();
    }


    int absFingerCenterXPointIndex;
    int fixPoint;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                startX = event.getX();
                startY = event.getY();
                mode = 1;
                return true;
            case MotionEvent.ACTION_MOVE:
                if (event.getPointerCount() == 2) {
                    double newDist = spacing(event);
                    scale = newDist/oldDist;
                    fixPoint = (int)(fingerCenterX/width*(end-start));
                    accumulate_scale *= scale;
                    if(accumulate_scale<1){
                        accumulate_scale = 1;
                    }
                    oldDist = newDist;
                     invalidate();
                    break;
                }
                 if (event.getPointerCount() == 1 && mode == 1) {
                    float newX = event.getX();
                    float newY = event.getY();
                    offsetX += (int) (startX - newX);
                    startX = newX;
                    startY = newY;
                    fingerCenterX = 0;
                    fingerCenterY = 0;
                    fixPoint = 0;
                     if(offsetX<0) offsetX =0;
                    if(offsetX+width>mPoints.size()*accumulate_scale) offsetX=mPoints.size()*accumulate_scale-width;
                    invalidate();
                    break;
                }
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                mode = 2;
                oldDist = spacing(event);
                fingerCenterX = getCenter(event.getX(0), event.getX(1));
                fingerCenterY = getCenter(event.getY(0),event.getY(1));
                absFingerCenterXPointIndex = (int) (fingerCenterX/width*(end-start)+start);

                break;
            case MotionEvent.ACTION_POINTER_UP:
                break;
            case MotionEvent.ACTION_UP:
                mode = 0;

                break;
        }
        return super.onTouchEvent(event);
    }

    private int getCenter(float x1,float x2){
        return (int) (Math.min(x1,x2)+Math.abs(x1-x2)/2);
    }

    private double spacing(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return Math.sqrt(x * x + y * y);
    }

}
